
#include "handler.h"

// #include <chrono>  // import std::chrono
// #include <thread>  // import std::thread

#include "EventLoop.h"  // import setTimeout, setInterval
#include "hbase.h"
#include "hfile.h"
#include "hstring.h"
#include "htime.h"
#include "utils/auth.h"
#include <regex>

int Handler::preprocessor(HttpRequest* req, HttpResponse* resp) {
    // Deserialize request body to json, form, etc.
    req->ParseBody();

    // Unified setting response Content-Type?
    resp->content_type = APPLICATION_JSON;

    return HTTP_STATUS_NEXT;
}

int Handler::postprocessor(HttpRequest* req, HttpResponse* resp) {
    return resp->status_code;
}

int Handler::Authorization(HttpRequest* req, HttpResponse* resp) {
    std::string bearer = req->GetHeader("Authorization");
    std::string token;
    if (!bearer.empty()) {
        // 使用正则表达式匹配 Bearer token
        std::regex bearerRegex("Bearer\\s+(\\S+)");
        std::smatch match;

        if (std::regex_search(bearer, match, bearerRegex) && match.size() > 1) {
            token = match[1].str();
        }
    }

    if (hv::startswith(req->Path(), "/admin")) {
        if (bearer.empty() || !AuthHandler->is_admin_login(token)) {
            response_status(resp, 10011, "Miss Authorization!");
            return HTTP_STATUS_UNAUTHORIZED;
        }
    } else if (hv::startswith(req->Path(), "/user")) {
        if (bearer.empty() || !AuthHandler->is_admin_login(token) || !AuthHandler->is_user_login(token)) {
            response_status(resp, 10012, "Miss Authorization!");
            return HTTP_STATUS_UNAUTHORIZED;
        }
    } else if (hv::startswith(req->Path(), "/cars")) {
        if (bearer.empty() || !AuthHandler->is_czgw_login(token)) {
            response_status(resp, 10013, "Miss Authorization!");
            return HTTP_STATUS_UNAUTHORIZED;
        }
    }

    return HTTP_STATUS_NEXT;
}

int Handler::route_path(const HttpContextPtr& ctx, const std::string dir) {
    std::string path      = ctx->param("path");
    std::string full_path = HPath::join(dir, path);

    // 安全检查：确保访问路径在dir内
    if (!hv::startswith(full_path, dir)) {
        return ctx->response->status_code = HTTP_STATUS_FORBIDDEN;
    }

    struct stat st;
    if (stat(full_path.c_str(), &st) != 0) {
        return ctx->response->status_code = HTTP_STATUS_NOT_FOUND;
    }

    // 处理目录
    if (S_ISDIR(st.st_mode)) {
        DIR* real_dir;
        struct dirent* ent;
        std::stringstream content;
        content << "<html><body><h3>Directory listing for " << dir.c_str() << "</h3><ul>";

        if ((real_dir = opendir(full_path.c_str())) != NULL) {
            while ((ent = readdir(real_dir)) != NULL) {
                // 安全检查：移除路径中的 ".", ".." 以防止目录遍历攻击
                if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
                    // 只返回普通文件
                    if (ent->d_type == DT_REG) {
                        content << "<li><a href=\"/logs/" << (path.empty() ? "" : path + "/") << ent->d_name << "\">"
                                << ent->d_name << "</a></li>";
                    }
                }
            }
            closedir(real_dir);
        }

        content << "</ul></body></html>";
        ctx->response->SetBody(content.str());
        ctx->response->SetContentType("text/html");
        return ctx->response->status_code = HTTP_STATUS_OK;
    } else if (S_ISREG(st.st_mode)) {
        return (http_status)ctx->sendFile(full_path.c_str());
    } else {
        return ctx->response->status_code = HTTP_STATUS_FORBIDDEN;
    }
}